#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkInterface>
#include "networkmanager.h"

#ifdef QT_DEBUG
const QString BASE_URL = "http://tenant.gateway.xsq-inc.com/tenant/program/api/v1"; //测试地址
const QString ApplicationCode = "c93aa71d8"; //测试编码
#else
const QString BASE_URL = "https://tenant-gateway.xsq-inc.net/tenant/program/api/v1"; //正式地址
const QString ApplicationCode = "4af1d70cf"; //正式编码
#endif

const QString Login_url = BASE_URL + "/open/application/login";
const QString QueryPrinterTemplate_url = BASE_URL + "/open/application/clientQueryPrintTemplate";
const QString QueryMerterialList_url = BASE_URL + "/open/application/queryMaterialList";
const QString QueryRecordList_url = BASE_URL + "/open/application/clientQueryMaterialRecordList";
const QString UploadRecordList_url = BASE_URL + "/open/application/clientMaterialUpload";
const QString DeleteRecordList_url = BASE_URL + "/open/application/clientMaterialDelete";
const QString ChangePassword_url = BASE_URL + "/open/application/clientUpdatePassword";

NetworkManager::NetworkManager(QObject *parent)
    : QObject{parent}
{
}

QString NetworkManager::getMacAddress(){
    QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
    QString macAddr;

    foreach (const QNetworkInterface &interface, interfaces) {
        // 筛选条件：接口已启用、正在运行、非回环地址
        if (interface.flags().testFlag(QNetworkInterface::IsUp) &&
            interface.flags().testFlag(QNetworkInterface::IsRunning) &&
            !interface.flags().testFlag(QNetworkInterface::IsLoopBack)) {

            macAddr = interface.hardwareAddress();
            break; // 找到第一个有效接口后退出
        }
    }
    return macAddr;
}


QtPromise::QPromise<QJsonObject> NetworkManager::Login(
    const QString& tenant,
    const QString& username,
    const QString& password)
{
    QJsonObject root;
    QJsonObject data;
    data["tenantSign"] = tenant;
    data["account"] = username;
    data["password"] = password;
    data["applicationCode"] = ApplicationCode;
    root["data"] = data;

    return QtPromise::QPromise<QJsonObject>([=](const auto& resolve, const auto& reject) {
        auto conn = std::make_shared<QMetaObject::Connection>();
        *conn = connect(&client, &SecureHttpClient::responseReady,
                        [=](const QJsonObject& response) {
                            disconnect(*conn);
                            if (response["token"].isUndefined()) {
                                reject(QString("Invalid token"));
                                return;
                            }
                            token = response["token"].toString();
                            QJsonObject info;
                            info["tenantSign"] = response["tenantSign"].toString();
                            info["shopCode"] = response["userCode"].toString();
                            info["shopName"] = response["userName"].toString();
                            resolve(info);
                        });

        connect(&client, &SecureHttpClient::requestFailed,
                [=](int code, const QString& error) {
                    disconnect(*conn);
                    reject(NetErrorInfo{code, error, QDateTime::currentDateTime()});
                });

        client.post(Login_url, nullptr, QJsonDocument(root).toJson());
    });
}

QtPromise::QPromise<QJsonObject> NetworkManager::QueryPrinterTemplate()
{
    return QtPromise::QPromise<QJsonObject>([=](const auto& resolve, const auto& reject) {
        auto conn = std::make_shared<QMetaObject::Connection>();
        *conn = connect(&client, &SecureHttpClient::responseReady,
                        [=](const QJsonObject& data) {
                            disconnect(*conn);
                            QJsonObject info;
                            QJsonObject detail = data["detail"].toObject();
                            info["printerDpi"] = QString::number(detail["printerDpi"].toInt());
                            info["printerIp"] = detail["printerIp"].toString();
                            info["printerName"] = detail["printerName"].toString();
                            info["vShift"] = detail["vShift"].toString();
                            info["hShift"] = detail["hShift"].toString();
                            info["printerPort"] = detail["printerPort"].toString();
                            info["printerXML"] = detail["printerXml"].toString();
                            resolve(info);
                        });

        connect(&client, &SecureHttpClient::requestFailed,
                [=](int code, const QString& error) {
                    disconnect(*conn);
                    reject(NetErrorInfo{code, error, QDateTime::currentDateTime()});
                });

        QJsonObject root;
        root["data"] = QJsonObject();
        client.post(QueryPrinterTemplate_url, token, QJsonDocument(root).toJson());
    });
}

QtPromise::QPromise<QJsonObject> NetworkManager::QueryMerterialList()
{
    QJsonObject data;
    data["index"] = 1;
    data["size"] = 999;
    data["templateVersion"] = "";

    return QtPromise::QPromise<QJsonObject>([=](const auto& resolve, const auto& reject) {
        auto conn = std::make_shared<QMetaObject::Connection>();
        *conn = connect(&client, &SecureHttpClient::responseReady,
                        [=](const QJsonObject& data) {
                            disconnect(*conn);
                            resolve(data);
                        });

        connect(&client, &SecureHttpClient::requestFailed,
                [=](int code, const QString& error) {
                    disconnect(*conn);
                    reject(NetErrorInfo{code, error, QDateTime::currentDateTime()});
                });

        QJsonObject root;
        root["data"] = data;
        client.post(QueryMerterialList_url, token, QJsonDocument(root).toJson());
    });
}

QtPromise::QPromise<QJsonObject> NetworkManager::QueryMaterialRecordList()
{
    return QtPromise::QPromise<QJsonObject>([=](const auto& resolve, const auto& reject) {
        auto conn = std::make_shared<QMetaObject::Connection>();
        *conn = connect(&client, &SecureHttpClient::responseReady,
                        [=](const QJsonObject& data) {
                            disconnect(*conn);
                            resolve(data);
                        });

        connect(&client, &SecureHttpClient::requestFailed,
                [=](int code, const QString& error) {
                    disconnect(*conn);
                    reject(NetErrorInfo{code, error, QDateTime::currentDateTime()});
                });
        QJsonObject root;
        root["data"] = QJsonObject();
        client.post(QueryRecordList_url, token, QJsonDocument(root).toJson());
    });
}

QtPromise::QPromise<QJsonObject> NetworkManager::UploadRecords(QJsonArray list)
{
    QJsonObject data;
    data["list"] = list;

    return QtPromise::QPromise<QJsonObject>([=](const auto& resolve, const auto& reject) {
        auto conn = std::make_shared<QMetaObject::Connection>();
        *conn = connect(&client, &SecureHttpClient::responseReady,
                        [=](const QJsonObject& data) {
                            disconnect(*conn);
                            resolve(data);
                        });

        connect(&client, &SecureHttpClient::requestFailed,
                [=](int code, const QString& error) {
                    disconnect(*conn);
                    reject(NetErrorInfo{code, error, QDateTime::currentDateTime()});
                });

        QJsonObject root;
        root["data"] = data;
        client.post(UploadRecordList_url, token, QJsonDocument(root).toJson());
    });
}

QtPromise::QPromise<QJsonObject> NetworkManager::ChangePassword(QString oldPassword, QString newPassword)
{
    QJsonObject data;
    data["oldPassword"] = oldPassword;
    data["newPassword"] = newPassword;

    return QtPromise::QPromise<QJsonObject>([=](const auto& resolve, const auto& reject) {
        auto conn = std::make_shared<QMetaObject::Connection>();
        *conn = connect(&client, &SecureHttpClient::responseReady,
                        [=](const QJsonObject& data) {
                            disconnect(*conn);
                            resolve(data);
                        });

        connect(&client, &SecureHttpClient::requestFailed,
                [=](int code, const QString& error) {
                    disconnect(*conn);
                    reject(NetErrorInfo{code, error, QDateTime::currentDateTime()});
                });

        QJsonObject root;
        root["data"] = data;
        client.post(ChangePassword_url, token, QJsonDocument(root).toJson());
    });
}
